package com.xbongbong.paas.service.log.crm.operation;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.message.domain.entity.PushEntity;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.entity.OperateLogEntity;
import com.xbongbong.paas.log.model.OperateLogModel;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.service.log.crm.help.OperationLogHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.enums.CommunicatePlanNotifyTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.pro.listbatch.pojo.dto.ArchiveDTO;
import com.xbongbong.pro.listbatch.pojo.dto.UpdateRemindDTO;
import com.xbongbong.pro.log.pojo.DetailLogComplexPojo;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.log.pojo.dto.AddBatchPushNotifyDTO;
import com.xbongbong.pro.log.pojo.dto.AddFocusDTO;
import com.xbongbong.pro.log.pojo.dto.AddOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.AddPushNotifyDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteBatchOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteFocusDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeletePushNotifyDTO;
import com.xbongbong.pro.log.pojo.dto.OperateArchiveDTO;
import com.xbongbong.pro.log.pojo.dto.UpdateBatchOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.UpdateOperationLogDTO;
import com.xbongbong.pro.message.model.PushModel;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.base.CommunicateBaseEnum;
import com.xbongbong.saas.enums.business.PushNotifyEnum;
import com.xbongbong.saas.enums.dictionary.ArchivedEnum;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: yingjianfeng
 * @date: 2022/4/13 16:39
 * @description: crm操作日志抽象接口
 */
@Slf4j
public abstract class AbstractCrmOperationLogHandle extends AbstractOperationLogHandle{
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private OperateLogModel operateLogModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    @Lazy
    private OperationLogHelp operationLogHelp;
    @Resource
    private PushModel pushModel;
    @Resource
    private FormDataHelp formDataHelp;
    /**
     * 从之前吴峰老哥的方法移过来的
     * date: 2022/7/8 9:48 上午
     * @author yingjf
     * @param formDataAddDTO:
     * @param paasFormDataEntity:
     * @param logName:
     * @param name:
     * @param operateModuleTypeEnum:
     * @param saveVO:
     * @param beforeSaveVO:
     * @param paasFormName:
     * @param memo:
     */
    protected void addSaveLogger(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity, String logName, String name, OperateModuleTypeEnum operateModuleTypeEnum, SaveVO saveVO,
                                 BeforeSaveVO beforeSaveVO,String paasFormName,String memo) throws XbbException {
        boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
        if (isImport) {
            return;
        }
        String corpid = formDataAddDTO.getCorpid();
        Long dataId = saveVO.getDataId();
        // 记录日志(有名称的格式为编号(名称)，无名称的格式为编号)
        OperateTypeEnum operateTypeEnum = OperateTypeEnum.NEW;
        if (Objects.equals(1, formDataAddDTO.getIsBusinessRule())) {
            // 自定义表单才允许插入
            operateTypeEnum = OperateTypeEnum.RULE_NEW;
        }
        UserVO userVO = saveVO.getUserVO();
        String userName = userVO.getName();
        String userId = userVO.getUserId();
        Long formId = formDataAddDTO.getFormId();
        if(StringUtils.isEmpty(paasFormName)){
            paasFormName = getPaasFormName(corpid, formId, formDataAddDTO.getBusinessType());
        }
        if(StringUtils.isEmpty(memo)){
            memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_ADD_WORK), userName, paasFormName, logName);
        }
        mongoLogHelp.buildLog(corpid, userId, userName, operateModuleTypeEnum, operateTypeEnum, dataId.toString(), logName, memo, formDataAddDTO.getHttpHeader());
    }
    /**
     * 从之前吴峰老哥的方法移过来的 重载了一下
     * date: 2022/7/8 9:49 上午
     * @author yingjf
     * @param formDataAddDTO:
     * @param paasFormDataEntity:
     * @param logName:
     * @param name:
     * @param operateModuleTypeEnum:
     * @param saveVO:
     * @param beforeSaveVO:
     */
    protected void addSaveLogger(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity, String logName, String name, OperateModuleTypeEnum operateModuleTypeEnum, SaveVO saveVO,
                                 BeforeSaveVO beforeSaveVO) throws XbbException {
        addSaveLogger( formDataAddDTO,  paasFormDataEntity,  logName,  name,  operateModuleTypeEnum,  saveVO, beforeSaveVO,null,null);
    }


    /**
     * 从之前的代码抽离过来的
     * date: 2022/6/24 10:44 上午
     * @author yingjf
     * @param formDataUpdateDTO:
     * @param paasFormDataEntity:
     * @param redundantTemplateTypeEnum:
     * @param logMemo:
     * @param opObjectName:
     * @param operateModuleTypeEnum:
     * @param updateVO:
     * @param beforeUpdateVO:
     * @param operateTypeEnum:
     * @param indexTypeEnum:
     */
    protected void updateSaveLogger(FormDataUpdateDTO formDataUpdateDTO, PaasFormDataEntity paasFormDataEntity, RedundantTemplateTypeEnum redundantTemplateTypeEnum, String logMemo,
                                    String opObjectName, OperateModuleTypeEnum operateModuleTypeEnum, UpdateVO updateVO,
                                    BeforeUpdateVO beforeUpdateVO, OperateTypeEnum operateTypeEnum, IndexTypeEnum indexTypeEnum) throws XbbException {
        boolean isCoverage = Objects.equals(1, formDataUpdateDTO.getIsCover());
        if (isCoverage) {
            return;
        }
        String corpid = formDataUpdateDTO.getCorpid();
        String userName = updateVO.getUserVO().getName();
        String userId = updateVO.getUserVO().getUserId();
        // 用了处理日志中的子表单数据
        if (Objects.nonNull(paasFormDataEntity.getSubFormData())) {
            paasFormDataEntity.getData().putAll(paasFormDataEntity.getSubFormData());
        }
        if (Objects.nonNull(beforeUpdateVO.getOldPaasFormData())&&Objects.nonNull(beforeUpdateVO.getOldPaasFormData().getSubFormData())) {
            beforeUpdateVO.getOldPaasFormData().getData().putAll(beforeUpdateVO.getOldPaasFormData().getSubFormData());
        }
        JSONObject newObj = JsonHelperUtil.parseObject(JSONObject.toJSONString(paasFormDataEntity));
        JSONObject oldObj = JsonHelperUtil.parseObject(JSONObject.toJSONString(beforeUpdateVO.getOldPaasFormData()));
        List<DetailLogPojo> detailArr = logHelp.getDetailArr4Data(corpid, redundantTemplateTypeEnum, beforeUpdateVO.getExplainMap(), oldObj, newObj);
        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, userName, operateModuleTypeEnum, operateTypeEnum, formDataUpdateDTO.getDataId().toString(), opObjectName, logMemo, formDataUpdateDTO.getHttpHeader());
    }
    /**
     * 封装下更新的入参
     * date: 2022/4/22 11:19 上午
     * @Author yingjf
     * @param corpid: 公司id
     * @param userId: 用户id
     * @param userName: 用户名
     * @param paasFormEntityExt: 表单实体
     * @param newData: 新数据
     * @param oldData: 老数据
     * @param explainMap:解释map
     * @param httpHeader:请求头
     */
    protected UpdateOperationLogDTO packageUpdateParams(String corpid, String userId, String userName,
                                                        PaasFormEntityExt paasFormEntityExt, PaasFormDataEntity newData, PaasFormDataEntity oldData,
                                                        Map<String, FieldAttrEntity> explainMap, String httpHeader, Integer editLable){
        UpdateOperationLogDTO updateOperationLogDTO = new UpdateOperationLogDTO();
        updateOperationLogDTO.setEditLable(editLable);
        FormDataUpdateDTO formDataUpdateDTO = new FormDataUpdateDTO();
        formDataUpdateDTO.setIsCover(0);
        formDataUpdateDTO.setClueId(null);
        formDataUpdateDTO.setCorpid(corpid);
        formDataUpdateDTO.setDataId(oldData.getDataId());
        formDataUpdateDTO.setHttpHeader(httpHeader);
        updateOperationLogDTO.setFormDataUpdateDTO(formDataUpdateDTO);

        UpdateVO updateVO = new UpdateVO();
        UserVO userVO = new UserVO();
        userVO.setUserId(userId);
        userVO.setName(userName);
        updateVO.setUserVO(userVO);
        updateVO.setPaasFormDataEntity(newData);
        updateOperationLogDTO.setUpdateVO(updateVO);

        BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO();
        beforeUpdateVO.setPaasFormEntityExt(paasFormEntityExt);
        beforeUpdateVO.setOldPaasFormData(oldData);
        beforeUpdateVO.setExplainMap(explainMap);
        updateOperationLogDTO.setBeforeUpdateVO(beforeUpdateVO);
        return updateOperationLogDTO;
    }


    @Override
    @Async("sysLogThreadPool")
    public void updateBatch(UpdateBatchOperationLogDTO updateBatchOperationLogDTO){
        OperateModuleTypeEnum operateModuleTypeEnum = operationLogHelp.getOperateModule(type());
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(type().get(0));
        updateBatch(updateBatchOperationLogDTO,redundantTemplateTypeEnum,operateModuleTypeEnum);
    }

    /**
     * 批量公共方法
     * date: 2022/4/22 1:51 下午
     * @Author yingjf
     * @param updateBatchOperationLogDTO: 数据
     * @param redundantTemplateTypeEnum:
     * @param operateModuleTypeEnum: 操作模块
     */
    private void updateBatch(UpdateBatchOperationLogDTO updateBatchOperationLogDTO,RedundantTemplateTypeEnum redundantTemplateTypeEnum,OperateModuleTypeEnum operateModuleTypeEnum){
        try {
            String corpid = updateBatchOperationLogDTO.getCorpid();
            String userId = updateBatchOperationLogDTO.getOpUserId();
            String loginUserName = updateBatchOperationLogDTO.getOpUserName();
            Integer isBatch = updateBatchOperationLogDTO.getIsBatch();
            String httpHeader = updateBatchOperationLogDTO.getHttpHeader();
            Integer allowUpdateDataSize = updateBatchOperationLogDTO.getAllowUpdateDataSize();
            Long formId = updateBatchOperationLogDTO.getFormId();
            Integer businessType = updateBatchOperationLogDTO.getBusinessType();
            List<AttrValuePojo> logAVList = updateBatchOperationLogDTO.getLogAVList();
            List<String> attrList = logAVList.stream().map(AttrValuePojo::getAttr).collect(Collectors.toList());
            List<String> attrNameList = logAVList.stream().map(AttrValuePojo::getAttrName).collect(Collectors.toList());
            PaasFormExplainEntity explainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
            Map<String, FieldAttrEntity> editedFieldExplainMap = ExplainUtil.getExplainMapByAttrList(explainEntity.getExplains(), attrList);
            List<PaasFormDataEntity> oldDataList = updateBatchOperationLogDTO.getOldDataList();
            List<PaasFormDataEntity> newDataList = updateBatchOperationLogDTO.getNewDataList();
            Map<Long,PaasFormDataEntity> oldDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(PaasFormDataEntity item: oldDataList){
                oldDataMap.put(item.getDataId(),item);
            }
            Map<Long,PaasFormDataEntity> newDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(PaasFormDataEntity item: newDataList){
                newDataMap.put(item.getDataId(),item);
            }
            PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(formId, businessType, corpid);
            // 批量
            if(Objects.equals(1,isBatch)){
                String memo = "";
                String attrName = StringUtils.join(attrNameList,"，");
                if(checkIsPublic(oldDataList.get(0).getData())){
                    // 公海池批量编辑文案有区别 目前只有客户的
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR_IN_PUBLIC), loginUserName, paasFormEntity.getName(), attrName,allowUpdateDataSize);
                }else{
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, paasFormEntity.getName(), attrName,allowUpdateDataSize);
                }
                List<DetailLogComplexPojo> detailArr = new ArrayList<>();
                for(PaasFormDataEntity oldData: oldDataList){
                    Long dataId = oldData.getDataId();
                    PaasFormDataEntity newData = newDataMap.get(dataId);
                    List<DetailLogPojo> childList = logHelp.getDetailArr4Data(corpid, redundantTemplateTypeEnum, editedFieldExplainMap, JsonHelperUtil.parseObject(JSONObject.toJSONString(oldData)), JsonHelperUtil.parseObject(JSONObject.toJSONString(newData)));
                    JSONObject data = oldData.getData();
                    String opObjectName = data.getString(operationLogHelp.getNameAttr(type()));
                    DetailLogComplexPojo detailLogPojo = new DetailLogComplexPojo(opObjectName, childList);
                    detailArr.add(detailLogPojo);
                }
                mongoLogHelp.buildLog4ComplexDetailArr(BasicConstant.TWO,detailArr, corpid, userId, loginUserName,  operateModuleTypeEnum, OperateTypeEnum.EDIT, "", "", memo, httpHeader);
            }else{
                UpdateOperationLogDTO updateOperationLogDTO = packageUpdateParams(corpid, userId, loginUserName, (PaasFormEntityExt) paasFormEntity, newDataList.get(0), oldDataList.get(0), editedFieldExplainMap, httpHeader,Objects.equals(isBatch,2)?1:0);
                updateOperationLogDTO.getBeforeUpdateVO().setExplainMap(editedFieldExplainMap);
                // 这里直接调单条更新的 fix 这里只有两个参数，没有比较调下面的方法，优化下
                update(updateOperationLogDTO);
            }
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle.updateBatch ", e);
        }
    }

    /**
     * 校验是否在公海池
     * date: 2022/7/8 9:45 上午
     * @author yingjf
     * @param data: 数据
     */
    private Boolean checkIsPublic(JSONObject data) throws XbbException{
        return OperationLogHelp.checkIsPublic(data,type().get(0));
    }


    /**
     * 通用新增跟进提醒
     * date: 2022/4/24 10:39 上午
     * @Author yingjf
     * @param addPushNotifyDTO:入参
     */
    @Async("sysLogThreadPool")
    public void addPushNotify(AddPushNotifyDTO addPushNotifyDTO){
        try {
            String loginUserName = addPushNotifyDTO.getUserName();
            JSONObject dataList = addPushNotifyDTO.getDataList();
            String corpid = addPushNotifyDTO.getCorpid();
            Long formId = addPushNotifyDTO.getFormId();
            Integer businessType = addPushNotifyDTO.getBusinessType();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            JSONArray jsonArray = new JSONArray();
            StringBuffer linkNameBuffer = new StringBuffer();
            // 关联多条的数据信息 name id businesstype
            JSONArray array = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PushNotifyEnum.NOTIFY_NAME.getAttr(), jsonArray);
            JSONObject jsonObject = JsonHelperUtil.parseObject(array.get(0).toString());
            String name = jsonObject.getString("name");
            linkNameBuffer.append(name);
            //拿到提醒的标题
            String title = dataList.getString(CommunicateBaseEnum.MAIN_BUSINESS.getAttr());
            String opObjectName = String.format(I18nMessageUtil.getMessage(
                    CrmLogMemoConstant.LOG_OPERATION_OBJECT_FORM_OBJECT_PUSH_NOTIFY),paasFormName,linkNameBuffer);
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.PUSH_NOTIFY_LOG_MEMO_VALUE), loginUserName,paasFormName, linkNameBuffer.toString(), title);
            OperateLogEntity logEntity = new OperateLogEntity(corpid, addPushNotifyDTO.getUserId(), loginUserName, OperateModuleTypeEnum.PUSH_NOTIFY, OperateTypeEnum.NEW, null, opObjectName, memo, addPushNotifyDTO.getHttpHeader(), null);
            operateLogModel.insert(logEntity);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.AbstractCrmOperationLogHandle.addPushNotify", e);
        }
    }
    /**
     * 通用批量新增跟进提醒
     * date: 2022/4/24 10:59 上午
     * @Author yingjf
     * @param addBatchPushNotifyDTO:
     */
    @Async("sysLogThreadPool")
    public void addBatchPushNotify(AddBatchPushNotifyDTO addBatchPushNotifyDTO){
        try {
            String loginUserName = addBatchPushNotifyDTO.getUserName();
            JSONObject dataList = addBatchPushNotifyDTO.getDataList();
            String httpHeader = addBatchPushNotifyDTO.getHttpHeader();
            String corpid = addBatchPushNotifyDTO.getCorpid();
            String userId = addBatchPushNotifyDTO.getUserId();
            Long formId = addBatchPushNotifyDTO.getFormId();
            Integer businessType = addBatchPushNotifyDTO.getBusinessType();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            JSONArray jsonArray = new JSONArray();
            StringBuffer linkNameBuffer = new StringBuffer();
            JSONArray arrayrr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PushNotifyEnum.NOTIFY_NAME.getAttr(), jsonArray);
            for (Object object : arrayrr) {
                JSONObject jsonObject = JsonHelperUtil.parseObject(object.toString());
                String name = jsonObject.getString("name");
                name = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_OPERATION_OBJECT_PUSH_NOTIFY), name);
                if (linkNameBuffer.length() == 0) {
                    linkNameBuffer.append(name);
                } else {
                    linkNameBuffer.append("、").append(name);
                }
            }
            //销售机会跟进提醒id
            JSONArray noArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PushNotifyEnum.NOTIFY_NAME.getAttr(), jsonArray);
            //拿到提醒的标题
            String title = dataList.getString(CommunicateBaseEnum.MAIN_BUSINESS.getAttr());
            //批量添加
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.PUSH_NOTIFY_LOG_MEMO_VALUE_BATCH), loginUserName, paasFormName, title, noArr.size());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_OPERATION_OBJECT));
            infoArrPojo.setContent(linkNameBuffer.toString());
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArrWithoutAsync(infoArrPojoList, corpid,userId, loginUserName, OperateModuleTypeEnum.PUSH_NOTIFY, OperateTypeEnum.NEW,
                    "", "", memo, httpHeader);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.AbstractCrmOperationLogHandle.addBatchPushNotify", e);
        }

    }

    /**
     * 通用删除跟进提醒
     * date: 2022/4/24 3:11 下午
     * @Author yingjf
     * @param deletePushNotifyDTO: 入参
     * @param attr: 比如客户取的是CustomerManagementEnum.NAME.getAttr()，机会传机会的
     */
    @Async("sysLogThreadPool")
    protected void deletePushNotify(DeletePushNotifyDTO deletePushNotifyDTO,String attr){
        try {
            String corpid = deletePushNotifyDTO.getCorpid();
            String userId = deletePushNotifyDTO.getOpUserId();
            String userName = deletePushNotifyDTO.getOpUserName();
            String nameStr = deletePushNotifyDTO.getOpObjectName();
            String httpHeader = deletePushNotifyDTO.getHttpHeader();
            OperateTypeEnum operateTypeEnum = deletePushNotifyDTO.getOperateType();
            String opObjectId = deletePushNotifyDTO.getOpObjectId();
            Long formId = deletePushNotifyDTO.getFormId();
            Integer businessType = deletePushNotifyDTO.getBusinessType();
            String title = deletePushNotifyDTO.getTitle();
            PaasFormDataEntityExt paasFormDataEntityExt = deletePushNotifyDTO.getPaasFormDataEntityExt();
            String opObject = "";
            if(Objects.isNull(nameStr)){
                // 获取
                nameStr = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), attr, "");
            }
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            opObject = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_OPERATION_OBJECT_FORM_OBJECT_PUSH_NOTIFY),paasFormName,nameStr);
            String memo = "";
            Boolean isPublic = checkIsPublic(paasFormDataEntityExt.getData());
            if(isPublic){
                memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_PUSH_NOTIFY_DELETE_IN_PUBLIC), userName, paasFormName, nameStr,title);
            }else{
                memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_PUSH_NOTIFY_DELETE), userName, paasFormName, nameStr,title);
            }
            mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PUSH_NOTIFY, operateTypeEnum,
                    opObjectId, opObject, memo, httpHeader);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.AbstractCrmOperationLogHandle.deletePushNotify",e);
        }
    }

    /**
     * 重载一下
     * date: 2022/4/27 10:12 上午
     * @Author yingjf
     * @param addFocusDTO:
     */
    protected void addFocus(AddFocusDTO addFocusDTO) {
        OperateModuleTypeEnum operateModuleTypeEnum = operationLogHelp.getOperateModule(type());
        addFocus( addFocusDTO,operateModuleTypeEnum);
    }
    /**
     * 添加关注
     * date: 2022/4/24 5:14 下午
     * @Author yingjf
     * @param addFocusDTO: 入参
     * @param operateModuleTypeEnum: 操作模块
     */
    protected void addFocus(AddFocusDTO addFocusDTO, OperateModuleTypeEnum operateModuleTypeEnum){
        try {
            String loginUserName = addFocusDTO.getOpUserName();
            Long dataId = addFocusDTO.getDataId();
            String corpid = addFocusDTO.getCorpid();
            Long formId = addFocusDTO.getFormId();
            Integer businessType = addFocusDTO.getBusinessType();
            String opUserId = addFocusDTO.getOpUserId();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            PaasFormDataEntityExt paasFormDataEntityExt = paasEsModel.getByKey(dataId, corpid, IndexTypeEnum.getByCode(businessType), null);
            String opObjectName = OperationLogHelp.getName(type(),paasFormDataEntityExt.getData());
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_FOCUS_ADD), loginUserName,paasFormName,opObjectName);
            OperateLogEntity logEntity = new OperateLogEntity(corpid, opUserId, loginUserName, operateModuleTypeEnum, OperateTypeEnum.FOCUS, null, opObjectName, memo, addFocusDTO.getHttpHeader(), null);
            operateLogModel.insert(logEntity);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.AbstractCrmOperationLogHandle.addPushNotify", e);
        }
    }

    protected void deleteFocus(DeleteFocusDTO deleteFocusDTO){
        deleteFocus(deleteFocusDTO,operationLogHelp.getOperateModule(type()));
    }
    /**
     * 添加关注
     * date: 2022/4/24 5:14 下午
     * @Author yingjf
     * @param deleteFocusDTO: 入参
     * @param operateModuleTypeEnum: 操作模块
     */
    protected void deleteFocus(DeleteFocusDTO deleteFocusDTO, OperateModuleTypeEnum operateModuleTypeEnum){
        try {
            String loginUserName = deleteFocusDTO.getOpUserName();
            Long dataId = deleteFocusDTO.getDataId();
            String corpid = deleteFocusDTO.getCorpid();
            Long formId = deleteFocusDTO.getFormId();
            Integer businessType = deleteFocusDTO.getBusinessType();
            String opUserId = deleteFocusDTO.getOpUserId();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            PaasFormDataEntityExt paasFormDataEntityExt = paasEsModel.getByKey(dataId, corpid, IndexTypeEnum.getByCode(businessType), null);
            String opObjectName = OperationLogHelp.getName(type(),paasFormDataEntityExt.getData());
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_FOCUS_DELETE), loginUserName,paasFormName,opObjectName);
            OperateLogEntity logEntity = new OperateLogEntity(corpid, opUserId, loginUserName, operateModuleTypeEnum, OperateTypeEnum.FOCUS, null, opObjectName, memo, deleteFocusDTO.getHttpHeader(), null);
            operateLogModel.insert(logEntity);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.AbstractCrmOperationLogHandle.addPushNotify", e);
        }
    }
    /**
     * 归档操作
     * date: 2022/7/8 9:46 上午
     * @author yingjf
     * @param operateArchiveDTO:
     */
    public void operate(OperateArchiveDTO operateArchiveDTO) {
        try {
            ArchiveDTO archiveDTO = operateArchiveDTO.getArchiveDTO();
            Integer businessType = archiveDTO.getBusinessType();
            Integer isBatch = operateArchiveDTO.getIsBatch();
            List<PaasFormDataEntityExt> dataList = operateArchiveDTO.getDataList();
            String userId = archiveDTO.getUserId();
            String userName = archiveDTO.getLoginUserName();
            List<Long> archIdIn = archiveDTO.getDataIdList();
            String corpid = archiveDTO.getCorpid();
            String nameStr = operateArchiveDTO.getNameStr();
            Integer archived = operateArchiveDTO.getArchived();
            OperateModuleTypeEnum operateModuleType = operateArchiveDTO.getOperateModuleType();
            OperateTypeEnum operateTypeEnum = ArchivedEnum.getOperateByCode(archived);
            String paasFormName = getPaasFormName(corpid, dataList.get(0).getFormId(), businessType);
            if(isBatch == 1){
                // 批量
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_ARCHIVE_FORM_DATA), userName, operateTypeEnum.getName(), paasFormName,archIdIn.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, operateModuleType, operateTypeEnum, "", "", memo, archiveDTO.getHttpHeader());
            } else {
                // 单个
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_ARCHIVE_FORM_DATA), userName, operateTypeEnum.getName(), paasFormName,nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, operateModuleType, operateTypeEnum, archIdIn.get(0).toString(), nameStr, memo, archiveDTO.getHttpHeader());
            }
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.add(com.xbongbong.pro.log.pojo.dto.AddArchiveDTO)",e);
        }

    }

    @Override
    @Async("sysLogThreadPool")
    public void update(UpdateOperationLogDTO updateOperationLogDTO) {
        try {
            FormDataUpdateDTO formDataUpdateDTO = updateOperationLogDTO.getFormDataUpdateDTO();
            UpdateVO updateVO = updateOperationLogDTO.getUpdateVO();
            BeforeUpdateVO beforeUpdateVO = updateOperationLogDTO.getBeforeUpdateVO();
            RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(type().get(0));
            boolean isCoverage = Objects.equals(1, formDataUpdateDTO.getIsCover());
            if (isCoverage) {
                return;
            }
            OperateModuleTypeEnum operateModuleTypeEnum = operationLogHelp.getOperateModule(type());
            PaasFormDataEntity paasFormDataEntity = updateVO.getPaasFormDataEntity();
            String opObjectName = OperationLogHelp.getName(type(),paasFormDataEntity.getData());
            String userName = updateVO.getUserVO().getName();
            String memoName = beforeUpdateVO.getPaasFormEntityExt().getName();
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_WORK), userName, memoName, opObjectName);
            updateSaveLogger(formDataUpdateDTO, paasFormDataEntity, redundantTemplateTypeEnum, memo, opObjectName, operateModuleTypeEnum, updateVO, beforeUpdateVO, OperateTypeEnum.EDIT, null);
        } catch (XbbException e) {
            log.error("com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle.update", e);
        }
    }


    @Override
    @Async("sysLogThreadPool")
    public void add(AddOperationLogDTO addOperationLogDTO) {
        try {
            FormDataAddDTO formDataAddDTO = addOperationLogDTO.getFormDataAddDTO();
            PaasFormDataEntity newPaasFormDataEntity = addOperationLogDTO.getNewPaasFormDataEntity();
            SaveVO saveVO = addOperationLogDTO.getSaveVO();
            BeforeSaveVO beforeSaveVO = addOperationLogDTO.getBeforeSaveVO();
            boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
            if (isImport) {
                return;
            }
            JSONObject data = newPaasFormDataEntity.getData();
            String logName = OperationLogHelp.getName(type(),data);
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(type().get(0));
            OperateModuleTypeEnum operateModuleTypeEnum = operationLogHelp.getOperateModule(type());
            addSaveLogger(formDataAddDTO, newPaasFormDataEntity, logName, xbbRefTypeEnum.getName(), operateModuleTypeEnum, saveVO, beforeSaveVO);
        } catch (XbbException e) {
            log.error("com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle.add", e);
        }
    }


    @Override
    @Async("sysLogThreadPool")
    public void delete(DeleteOperationLogDTO deleteOperationLogDTO) {
        try {
            String corpid = deleteOperationLogDTO.getCorpid();
            String userId = deleteOperationLogDTO.getOpUserId();
            String userName = deleteOperationLogDTO.getOpUserName();
            String nameStr = deleteOperationLogDTO.getOpObjectName();
            String httpHeader = deleteOperationLogDTO.getHttpHeader();
            OperateTypeEnum operateTypeEnum = deleteOperationLogDTO.getOperateType();
            String opObjectId = deleteOperationLogDTO.getOpObjectId();
            Long formId = deleteOperationLogDTO.getFormId();
            Integer businessType = deleteOperationLogDTO.getBusinessType();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, paasFormName, nameStr);
            OperateModuleTypeEnum operateModule = operationLogHelp.getOperateModule(type());
            mongoLogHelp.buildLog(corpid, userId, userName, operateModule, operateTypeEnum,
                    opObjectId, nameStr, memo, httpHeader);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle.delete", e);
        }
    }


    @Override
    @Async("sysLogThreadPool")
    public void deleteBatch(List<InfoArrPojo> infoArrPojoList, DeleteBatchOperationLogDTO deleteBatchOperationLogDTO) {
        try {
            String corpid = deleteBatchOperationLogDTO.getCorpid();
            String userId = deleteBatchOperationLogDTO.getOpUserId();
            String userName = deleteBatchOperationLogDTO.getOpUserName();
            String httpHeader = deleteBatchOperationLogDTO.getHttpHeader();
            OperateTypeEnum operateTypeEnum = deleteBatchOperationLogDTO.getOperateType();
            Integer allowDeleteDataSize = deleteBatchOperationLogDTO.getAllowDeleteDataSize();
            Long formId = deleteBatchOperationLogDTO.getFormId();
            Integer businessType = deleteBatchOperationLogDTO.getBusinessType();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, paasFormName, allowDeleteDataSize);
            OperateModuleTypeEnum operateModule = operationLogHelp.getOperateModule(type());

            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, operateModule, operateTypeEnum,
                    "", "", memo, httpHeader);
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.operation.impl.CustomerOperationLogHandleImpl.deleteBatch", e);
        }
    }


    /**
     * 更新操作日志
     * date: 2022/5/12 5:20 下午
     * @Author yingjf
     * @param updateRemindDTO:
     */
    @Async("sysLogThreadPool")
    public void edit(UpdateRemindDTO updateRemindDTO){
        try {
            Integer pushId = updateRemindDTO.getDataId().intValue();
            String corpid = updateRemindDTO.getCorpid();
            String userId = updateRemindDTO.getUserId();
            String userName = updateRemindDTO.getLoginUserName();
            PushEntity pushEntity = pushModel.getByKey(pushId,corpid);
            JSONObject dataList = updateRemindDTO.getDataList();
            JSONObject oldDataList = updateRemindDTO.getOldDataList();
            List<DetailLogPojo> detailArr = new ArrayList<>();
            for(PushNotifyEnum pushNotifyEnum:PushNotifyEnum.values() ){
                parseUpdatePushNotify(oldDataList,dataList,pushNotifyEnum,detailArr);
            }
            detailArr.add(new DetailLogPojo(StringConstant.UPDATE_TIME, I18nMessageUtil.getMessage(CommonConstant.UPDATE_TIME), DateUtil.getString(pushEntity.getAddTime()* 1000L, DateUtil.SDFYMDHM), DateUtil.getString(DateUtil.getLong(), DateUtil.SDFYMDHM)));
            List<HashMap<String,Object>> userList = (List<HashMap<String,Object>>)oldDataList.get(PushNotifyEnum.NOTIFY_NAME.getAttr());
            HashMap<String, Object> linkData = userList.get(0);
            String name = linkData.get("name").toString();
            Integer businessType = (Integer)linkData.get("businessType");
            Long dataId = Long.parseLong(linkData.get("id").toString());
            PaasFormDataEntityExt paasFormDataEntity = formDataHelp.getFormDataEntityExt(corpid, SaasMarkEnum.SAAS.getCode(), businessType, dataId);

            PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(paasFormDataEntity.getFormId(), businessType, corpid);
            String formName = paasFormEntity.getName();
            //用户“%s”编辑了%s“%s”的跟进提醒
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_PUSH_NOTIFY_EDIT), userName, formName, name);

            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, userName, OperateModuleTypeEnum.PUSH_NOTIFY, OperateTypeEnum.EDIT, updateRemindDTO.getDataId().toString(), String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_OPERATION_OBJECT_PUSH_NOTIFY),name), memo, updateRemindDTO.getHttpHeader());
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle.edit",e);
        }
    }

    /**
     * 日志解析跟进提醒
     * date: 2022/6/21 9:09 上午
     * @author yingjf
     * @param oldData: 老数据
     * @param newData: 新数据
     * @param pushNotifyEnum: 枚举
     * @param detailArr: 日志详情
     */
    private void parseUpdatePushNotify(JSONObject oldData,JSONObject newData,PushNotifyEnum pushNotifyEnum,List<DetailLogPojo> detailArr){
        String attr = pushNotifyEnum.getAttr();
        Object oldObject = oldData.get(attr);
        Object newObject = newData.get(attr);
        if(newObject==null || oldObject==null){
            return;
        }
        switch (pushNotifyEnum){
            case TITLE:
                String oldTitle = String.valueOf(oldObject);
                String newTitle = String.valueOf(newObject);
                if(!Objects.equals(oldTitle,newTitle)){
                    detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(), oldTitle, newTitle));
                }
                break;
            case NOTIFY_NAME:
                // 限制了改不了的
                break;
            case EXECUTOR:
                Map<Integer,String> oldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Integer,String> newMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

                List<HashMap<String,String>> oldList = (List) oldObject;
                for(HashMap<String,String> temp: oldList){
                    oldMap.put(Integer.parseInt(temp.get("value")),temp.get("text"));
                }

                List<HashMap> newList = (List) newObject;
                for(HashMap<String,String> temp: newList){
                    newMap.put(Integer.parseInt(temp.get("value")),temp.get("text"));
                }
                List<Integer> all = Arrays.asList(0,1,2);

                List<String> oldStrList = new ArrayList<>();
                List<String> newStrList = new ArrayList<>();
                for(Integer temp: all){
                    if(Objects.equals(2,temp)){
                        List<HashMap<String,String>> oldUserList =(List)oldData.get(PushNotifyEnum.EXECUTOR_LINKED_TEXT.getAttr());
                        List<HashMap<String,String>> newUserList =(List)newData.get(PushNotifyEnum.EXECUTOR_LINKED_TEXT.getAttr());
                        List<String> oldUserNameList = new ArrayList<>();
                        List<String> newUserNameList = new ArrayList<>();
                        if(oldUserList!=null){
                            for(HashMap<String,String> tempMap: oldUserList){
                                oldUserNameList.add(tempMap.get("name"));
                            }
                        }
                        if(newUserList!=null){
                            for(HashMap<String,String> tempMap: newUserList){
                                newUserNameList.add(tempMap.get("name"));
                            }
                        }
                        if(CollectionsUtil.isNotEmpty(oldUserNameList)){
                            oldStrList.add(StringUtils.join(oldUserNameList, ","));
                        }
                        if(CollectionsUtil.isNotEmpty(newUserNameList)){
                            newStrList.add(StringUtils.join(newUserNameList, ","));
                        }
                        continue;
                    }
                    if(Objects.nonNull(oldMap.get(temp))){
                        oldStrList.add(oldMap.get(temp));
                    }
                    if(Objects.nonNull(newMap.get(temp))){
                        newStrList.add(newMap.get(temp));
                    }
                }
                detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(), StringUtils.join(oldStrList, ";"), StringUtils.join(newStrList, ";")));
                break;
            case COMMUNICATE_TIME:
                int oldCommunicateTime = Integer.parseInt(oldObject+"");
                int  newCommunicateTime= Integer.parseInt(newObject+"");
                if(!Objects.equals(oldCommunicateTime,newCommunicateTime)){
                    detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(), DateUtil.getString(oldCommunicateTime), DateUtil.getString(newCommunicateTime)));
                }
                break;
            case NOTIFY_TYPE:
                Map<String,String> oldNotifyTypeMap = (HashMap)oldObject;
                Map<String,String> newNotifyTypeMap = (HashMap)newObject;
                if(!Objects.equals(oldNotifyTypeMap.get("value"),newNotifyTypeMap.get("value"))){
                    detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(),
                            oldNotifyTypeMap.get("text"),newNotifyTypeMap.get("text")));
                    if(Objects.equals(oldNotifyTypeMap.get("value"),CommunicatePlanNotifyTypeEnum.CUSTOM_TIME.getCode().toString())|| Objects.equals(newNotifyTypeMap.get("value"),CommunicatePlanNotifyTypeEnum.CUSTOM_TIME.getCode().toString())
                    ){
                        String oldNotifyTimeStr = "";
                        if(Objects.nonNull(oldData.get(PushNotifyEnum.NOTIFY_TIME.getAttr()))){
                            oldNotifyTimeStr = DateUtil.getString(Integer.parseInt(oldData.get(PushNotifyEnum.NOTIFY_TIME.getAttr()) + ""));
                        }
                        String newNotifyTimeStr = "";
                        if(Objects.nonNull(newData.get(PushNotifyEnum.NOTIFY_TIME.getAttr()))){
                            newNotifyTimeStr = DateUtil.getString(Integer.parseInt(newData.get(PushNotifyEnum.NOTIFY_TIME.getAttr()) + ""));
                        }

                        detailArr.add(new DetailLogPojo(PushNotifyEnum.NOTIFY_TIME.getAttr(), PushNotifyEnum.NOTIFY_TIME.getAttrName(), oldNotifyTimeStr, newNotifyTimeStr));
                    }
                }
                break;
            case REPEAT_NOTIFY:
                Map<String,String> oldRepeatNotifyMap = (HashMap)oldObject;
                Map<String,String> newRepeatNotifyMap = (HashMap)newObject;
                if(!Objects.equals(oldRepeatNotifyMap.get("value"),newRepeatNotifyMap.get("value"))) {
                    detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(),
                            oldRepeatNotifyMap.get("text"), newRepeatNotifyMap.get("text")));
                    if(!Objects.equals(oldRepeatNotifyMap.get("value"),CommunicatePlanNotifyTypeEnum.ADVANCE_ONE_QUARTER_HOUR.getCode().toString())|| !Objects.equals(newRepeatNotifyMap.get("value"),CommunicatePlanNotifyTypeEnum.ADVANCE_ONE_QUARTER_HOUR.getCode().toString())
                    ){
                        detailArr.add(new DetailLogPojo(PushNotifyEnum.LOOP_NUM.getAttr(), PushNotifyEnum.LOOP_NUM.getAttrName(), oldData.getString(PushNotifyEnum.LOOP_NUM.getAttr()), newData.getString(PushNotifyEnum.LOOP_NUM.getAttr())));
                    }
                }
                break;
            case ENTER_COMMUNICATE_PLAN:
            case MEMO:
                if(!Objects.equals(oldObject,newObject)){
                    detailArr.add(new DetailLogPojo(pushNotifyEnum.getAttr(), pushNotifyEnum.getAttrName(), oldObject.toString(), newObject.toString()));
                }
                break;
            default:
                break;
        }

    }


}
